\subsection{MIPS}

\lstinputlisting[caption=\Optimizing GCC 4.4.5 (IDA),style=customasmMIPS]{patterns/145_LCG/MIPS_O3_IDA_RU.lst}

Ух, мы видим здесь только одну константу (0x3C6EF35F или 1013904223).
Где же вторая (1664525)?

Похоже, умножение на 1664525 сделано только при помощи сдвигов и прибавлений!

Проверим эту версию:

\lstinputlisting[style=customc]{patterns/145_LCG/test.c}

\lstinputlisting[caption=\Optimizing GCC 4.4.5 (IDA),style=customasmMIPS]{patterns/145_LCG/test_O3_MIPS.lst}

Действительно!

\subsubsection{Перемещения в MIPS (\q{relocs})}

Ещё поговорим о том, как на самом деле происходят операции загрузки из памяти и запись в память.

Листинги здесь были сделаны в IDA, которая убирает немного деталей.

Запустим objdump дважды: чтобы получить дизассемблированный листинг и список перемещений:

\lstinputlisting[caption=\Optimizing GCC 4.4.5 (objdump)]{patterns/145_LCG/MIPS_O3_objdump.txt}

Рассмотрим два перемещения для функции \TT{my\_srand()}.

Первое, для адреса 0, имеет тип \TT{R\_MIPS\_HI16}, и второе, для адреса 8, имеет тип \TT{R\_MIPS\_LO16}.

Это значит, что адрес начала сегмента .bss будет записан в инструкцию по адресу 0 (старшая часть адреса)
и по адресу 8 (младшая часть адреса).

Ведь переменная \TT{rand\_state} находится в самом начале сегмента .bss.

Так что мы видим нули в операндах инструкций \LUI и \SW потому что там пока ничего нет~--- 
компилятор не знает, что туда записать.

Линкер это исправит и старшая часть адреса будет записана в операнд инструкции \LUI и младшая часть адреса~---
в операнд инструкции \SW.

\SW просуммирует младшую часть адреса и то что находится в регистре \$V0 (там старшая часть).

Та же история и с функцией my\_rand(): перемещение R\_MIPS\_HI16 указывает линкеру записать старшую часть
адреса сегмента .bss в инструкцию \LUI.

Так что старшая часть адреса переменной rand\_state находится в регистре \$V1.

Инструкция \LW по адресу 0x10 просуммирует старшую и младшую часть и загрузит значение переменной 
rand\_state в \$V0.

Инструкция \SW по адресу 0x54 также просуммирует и затем запишет новое значение в глобальную переменную
rand\_state.

IDA обрабатывает перемещения при загрузке, и таким образом эти детали скрываются.

Но мы должны о них помнить.

% TODO add example of compiled binary, GDB example, etc...
